require 'dgo/table/table'
module MapEditor
  module MapControler
    class MapDrawer
      include DGO::Table
      attr_accessor :draw_mode
      def initialize(palet_panel)
        @mode = :put
        @draw_mode = :pen
        @memory = nil
        @draw_sx = 0
        @draw_sy = 0
        @palet_panel = palet_panel
        @current_panel = nil
      end
      
      def target=(target)
        @target = target
      end
    
      def put_tile
        sx = @target.sx
        sy = @target.sy
        frame = @target.frame
        if @palet_panel.palet.active?

          @palet_panel.palet.each_chip_info do |palet_chip, tx, ty|
            ttx = (tx - (sx - @draw_sx) % @palet_panel.palet.frame.width) % @palet_panel.palet.frame.width
            tty = (ty - (sy - @draw_sy) % @palet_panel.palet.frame.height) % @palet_panel.palet.frame.height
            if @target.current_layer.map_data.exists?(sx + ttx, sy + tty)
              @target.current_layer.map_data[sx + ttx, sy + tty].palet_chip = palet_chip
            end
          end
          
          @target.map.render_new_part([@target.map.get_layer_texture(@target.current_layer_no)], [@target.current_layer], sx - 1 - @target.scroll_x_count, sy - 1 - @target.scroll_y_count, sx - 1, sy - 1, 2 + @palet_panel.palet.frame.width, 2 + @palet_panel.palet.frame.height)

        else
          @memory.each_with_two_index do |palet_chip, tx, ty|
            ttx = (tx - (sx - @draw_sx) % frame.width) % frame.width
            tty = (ty - (sy - @draw_sy) % frame.height) % frame.height
            if @target.current_layer.map_data.exists?(sx + ttx, sy + tty)
              @target.current_layer.map_data[sx + ttx, sy + tty].palet_chip = palet_chip
            end
          end
          
          @target.current_layer.update_complementary_data(sx - 1 - @target.scroll_x_count, sy - 1 - @target.scroll_y_count, sx - 1, sy - 1, 2 + @memory.width, 2 + @memory.height)
          @target.map.render_new_part([@target.map.get_layer_texture(@target.current_layer_no)], [@target.current_layer], sx - 1 - @target.scroll_x_count, sy - 1 - @target.scroll_y_count, sx - 1, sy - 1, 2 + @memory.width, 2 + @memory.height)
        end
      end
      
      def select(x, y)
        @target.sx = x
        @target.sy = y
        @target.ex = x
        @target.ey = y

        palet_chip = @target.current_layer.map_data[@target.sx, @target.sy].palet_chip
        
        @palet_panel.palet.active = true
        @palet_panel.palet.select_chip(palet_chip)
      end
      
      def set_default_frame(x, y)
        return unless @mode == :put
        @target.sx, @target.sy = @target.get_abs_location(x, y)

        if @palet_panel.palet.active?
          @target.ex = @target.sx + @palet_panel.palet.frame.width - 1
          @target.ey = @target.sy + @palet_panel.palet.frame.height - 1
          @target.frame.set_size(@palet_panel.palet.frame.width, @palet_panel.palet.frame.height)          
        else
          @target.ex = @target.sx + @target.frame.width - 1
          @target.ey = @target.sy + @target.frame.height - 1
        end
      end
      
      def on_double_clicked(event)
      
      end
      
      def on_left_down(event)
        return if @palet_panel.palet.nil?
        @draw_sx = @target.sx
        @draw_sy = @target.sy
   
        self.put_tile
        @target.invalidate(true, -1, -1, 2, 2)
      end
      
      def on_left_up(event)
      
      end
      
      def on_right_down(event)
        return if @palet_panel.palet.nil?
        tx, ty = @target.get_abs_location(event.x, event.y)
        return unless @target.current_layer.map_data.exists?(tx, ty)
        self.select(tx, ty)
        self.set_default_frame(event.x , event.y)
        @target.frame.set_size(1, 1)
        @target.invalidate(false)
        
      end
      
      def on_right_up(event)
        if @palet_panel.palet.nil?
          @target.frame.set_size(1, 1)
          return
        end

        @target.frame.set_size((@target.ex - @target.sx).abs + 1, (@target.ey - @target.sy).abs + 1)
        @mode = :put
        @memory = nil
        #unless @target.frame.width == 1 && @target.frame.height == 1
        arr = []
        (0 .. (@target.sy - @target.ey).abs).each do |ty|
          (0 .. (@target.sx - @target.ex).abs).each do |tx|
            arr << @target.current_layer.map_data[[@target.sx, @target.ex].min + tx, [@target.sy, @target.ey].min + ty].palet_chip
          end
        end

          @memory = Table.new((@target.sx - @target.ex).abs + 1, arr)
          @palet_panel.palet.active = false
        #end
        
        @target.invalidate(false)
      end
      
      def on_motion_right(event)
        @mode = :select
        ttx, tty = @target.get_abs_location(event.x, event.y, false)
        if @target.current_layer.map_data.exists?(ttx, tty)
          @target.ex, @target.ey = ttx, tty
        end
        @target.ex = [@target.ex, @target.right_count - 1].min
        @target.ey = [@target.ey, @target.bottom_count - 1].min
        @target.frame.set_size((@target.ex - @target.sx).abs + 1, (@target.ey - @target.sy).abs + 1)
      end
      
      def on_motion_left(event)
        @target.sx, @target.sy = @target.get_abs_location(event.x, event.y)
        self.put_tile
        return -1, -1, 2, 2
      end
      
      def on_motion(event)
        return if @palet_panel.palet.nil?
        @mode = :put
        tx, ty, tw, th = 0, 0, 0, 0
        if @target.left_pressed
          tx, ty, tw, th = self.on_motion_left(event) 
        end
        if @target.right_pressed
          self.on_motion_right(event)
        end
        self.set_default_frame(event.x, event.y)
        @target.invalidate(true, tx, ty, tw, th)
      end
      
      def render(s)
        return if @palet_panel.palet.nil?
        
        @target.frame.render(s, @target.grid_width, @target.grid_height,[@target.sx, @target.ex].min - @target.scroll_x_count, [@target.sy, @target.ey].min - @target.scroll_y_count)
      end
    end
  end
end